package com.sys.guacamole;

import org.apache.guacamole.protocol.GuacamoleConfiguration;

/**
 * 添加SSH连接
 * 如果您使用的是Guacamole内置的默认身份验证，并且希望向特定用户授予对SSH连接的访问​​权限，则需要在中找到该<authorize>用户的 部分 user-mapping.xml，并在其中添加以下部分：
 * <p>
 * <connection name =“ Unique Name”>
 * <protocol> ssh </ protocol>
 * <param name =“ serviceHostname”> localhost</ param>
 * <param name =“ servicePort”> 22</ param>
 * </ connection>
 * 如果完全按照上述方法添加，则名为“ Unique Name” 的新连接将可供与<authorize>包含它的部分关联的用户使用 。连接将使用SSH连接到localhostport 22。自然，您将要更改其中一些或所有值。
 * <p>
 * 如果要自动登录而不是在连接时收到登录提示，则可以指定用户名和密码以及其他 <param>标签。其他选项可用于控制字体。
 * <p>
 * 其他身份验证方法将提供描述如何配置新连接的文档。
 * <p>
 * <p>
 * 与VNC或RDP不同，SSH是文本协议。它在Guacamole中的实现实际上是终端仿真器和SSH客户端的组合，因为SSH协议并不是固有的图形化。Guacamole的SSH支持在服务器端模拟终端，并在客户端远程绘制该终端的屏幕。
 * <p>
 * libguac-client-ssh 库提供了对Guacamole的SSH支持，如果在构建过程中存在必需的依赖项，它将作为guacamole-server的一部分安装。
 */
public class GuacamoleSSH extends Guacamole {

    public GuacamoleSSH() {
        super();
    }

    /**
     * @param hostname 主机名称
     * @param port     主机端口
     */
    public GuacamoleSSH(String hostname, Integer port) {
        super(hostname, port);
    }

    /**
     * 网络参数
     * <p>
     * RDP连接需要定义目标计算机的主机名或IP地址。RDP端口定义为3389，在大多数情况下将为该值。如果不使用端口3389，则仅需要指定RDP端口。
     * <p>
     * SSH连接需要定义目标计算机的主机名或IP地址。SSH被标准化为使用端口22，在大多数情况下，这将是正确的值。如果不使用标准端口，则只需指定SSH端口。
     * <p>
     * Telnet连接需要定义目标计算机的主机名或IP地址。Telnet被标准化为使用端口23，并且在大多数情况下这将是正确的值。如果不使用标准端口，则只需指定telnet端口。
     *
     * @param hostname 子服务端ip
     * @param port     子服务端端口
     */
    public void setGuacamoleConfiguration(String hostname, Integer port) {
        this.setGuacamoleConfiguration(hostname, port, null, null);
    }

    /**
     * 网络参数
     * <p>
     * RDP连接需要定义目标计算机的主机名或IP地址。RDP端口定义为3389，在大多数情况下将为该值。如果不使用端口3389，则仅需要指定RDP端口。
     * <p>
     * SSH连接需要定义目标计算机的主机名或IP地址。SSH被标准化为使用端口22，在大多数情况下，这将是正确的值。如果不使用标准端口，则只需指定SSH端口。
     * <p>
     * Telnet连接需要定义目标计算机的主机名或IP地址。Telnet被标准化为使用端口23，并且在大多数情况下这将是正确的值。如果不使用标准端口，则只需指定telnet端口。
     *
     * @param hostname            子服务端ip SSH服务器Guacamole的主机名或IP地址应该连接到。
     *                            <p>
     * @param port                子服务端端口 SSH服务器正在侦听的端口，通常为22。此参数是可选的。如果未指定，将使用默认值22。
     *                            <p>
     * @param hostKey             SSH服务器的已知主机条目。此参数是可选的，并且，如果未提供，则不会验证主机身份。如果提供了参数，则将根据数据检查服务器的身份。
     *                            此参数的格式是OpenSSH known_hosts文件中单个条目的格式。
     *                            有关更多信息，请参见“ SSH主机验证”部分。
     *                            <p>
     * @param serverAliveInterval 缺省情况下，SSH客户端不向服务器发送keepalive请求。使用此参数可以配置客户端连接将保持活动数据包发送到服务器的时间间隔（以秒为单位）。
     *                            缺省值为0，表示禁用发送数据包。最小值是2。
     */
    public void setGuacamoleConfiguration(String hostname, Integer port, String hostKey, Integer serverAliveInterval) {
        super.guacamoleConfiguration = new GuacamoleConfiguration();
        super.guacamoleConfiguration.setProtocol("ssh");
        super.guacamoleConfiguration.setParameter("hostname", hostname);
        super.guacamoleConfiguration.setParameter("port", String.valueOf(port));
        if (hostKey != null) {
            super.guacamoleConfiguration.setParameter("host-key", hostKey);
        }
        if (serverAliveInterval != null) {
            super.guacamoleConfiguration.setParameter("server-alive-interval", String.valueOf(serverAliveInterval));
        }
    }

    /**
     * 认证方式
     * <p>
     * SSH通过密码和公用密钥身份验证提供身份验证。
     * <p>
     * 为了使鳄梨调味酱能够使用公钥身份验证，它必须有权访问您的私钥，以及密码（如果适用）。
     * 如果私钥需要密码，但未提供密码，则在连接时将提示您输入密码。
     * <p>
     * 如果未提供私钥，则鳄梨酱会尝试使用密码进行身份验证，从连接参数（如果提供）中读取该密码，或者直接提示用户。
     *
     * @param username   用于验证的用户名（如果有）。此参数是可选的。如果未指定，则在连接时将提示您输入用户名。
     *                   <p>
     * @param password   尝试身份验证时使用的密码（如果有）。此参数是可选的。如果未指定，则在连接时将提示您输入密码。
     *                   <p>
     * @param privateKey 用于公钥认证的私钥的全部内容。如果未指定此参数，将不使用公共密钥身份验证。
     *                   私钥必须采用OpenSSH格式，就像由OpenSSH ssh-keygen实用程序生成的那样。
     *                   <p>
     * @param passphrase 用于解密私钥以用于公钥身份验证的密码短语。如果私钥不需要密码，则不需要此参数。
     *                   如果私钥需要密码，但未提供此参数，则在连接时将提示用户输入密码。
     */
    public void authentication(String username, String password, String privateKey, String passphrase) {
        super.getGuacamoleConfiguration().setParameter("username", username);
        super.getGuacamoleConfiguration().setParameter("password", password);
        super.getGuacamoleConfiguration().setParameter("private-key", privateKey);
        super.getGuacamoleConfiguration().setParameter("passphrase", passphrase);
    }

    /**
     * 显示设置
     * <p>
     * Guacamole的SSH支持提供显示，但其含义与远程桌面协议（如VNC或RDP）不同。
     * 该显示是终端仿真器，因此提供了用于配置所用字体及其大小的选项。
     * 在这种情况下， 必须将所选字体安装在服务器上，因为服务器将处理呈现给终端显示器的字符，而不是客户端。
     *
     * @param colorScheme 用于SSH连接使用的终端仿真器的配色方案。它由以分号分隔的一系列名称/值对组成。
     *                    每个名称/值对之间用冒号分隔，并为终端仿真器调色板中的颜色分配一个值。例如，要默认使用白色背景上的蓝色文本，并将红色更改为紫色阴影。
     *                    <p>
     * @param fontName    要使用的字体名称。此参数是可选的。如果未指定，则将使用默认的“monospace”。
     *                    <p>
     * @param fontSize    要使用的字体大小，以点为单位。此参数是可选的。如果未指定，将使用默认值12。
     */
    public void displaySettings(ColorScheme colorScheme, String fontName, Integer fontSize) {
        super.getGuacamoleConfiguration().setParameter("color-scheme", colorScheme.getValue());
        if (fontName != null) {
            super.getGuacamoleConfiguration().setParameter("font-name", fontName);
        }
        if (fontSize != null) {
            super.getGuacamoleConfiguration().setParameter("font-size", String.valueOf(fontSize));
        }
    }

    /**
     * 运行命令（而不是shell）
     * <p>
     * 默认情况下，SSH会话将启动一个交互式外壳。
     * 将使用的shell由SSH服务器确定，通常是通过读取先前用chsh或 inside设置的用户默认shell来确定的/etc/passwd。
     * 如果要覆盖此设置，而是运行特定命令，可以通过在Guacamole SSH连接的配置中指定该命令来执行此操作。
     *
     * @param command 通过SSH会话执行的命令（如果有）。此参数是可选的。如果未指定，则SSH会话将使用用户的默认Shell。
     */
    public void runningCommand(String command) {
        if (command != null) {
            super.getGuacamoleConfiguration().setParameter("command", command);
        }
    }

    /**
     * 控制终端行为
     * <p>
     * 在大多数情况下，终端的默认行为无需修改即可工作。
     * 但是，当连接到某些系统，尤其是Linux以外的操作系统时，可能需要调整终端行为以使其正常运行。此部分中的设置控制该行为。
     *
     * @param ackspace     此参数控制退格键发送到远程系统的ASCII码。在大多数情况下，无需对此进行调整；
     *                     但是，如果在按Backspace键时看到控制字符（通常是^？或^ H）而不是看到已擦除的文本，则可能需要调整此参数。
     *                     默认情况下，如果未设置此选项，终端将发送ASCII码127（删除）。
     *                     <p>
     * @param terminalType 此参数设置传递到SSH服务器的终端仿真器类型字符串。此参数是可选的。如果未指定，linux则默认将“ ”用作终端仿真器类型。
     */
    public void ControllingTerminalBehavior(String ackspace, String terminalType) {
        if (ackspace != null) {
            super.getGuacamoleConfiguration().setParameter("ackspace", ackspace);
        }
        if (terminalType != null) {
            super.getGuacamoleConfiguration().setParameter("terminal-type", terminalType);
        }
    }

    /**
     * 文字会话录音（打字稿）
     * <p>
     * SSH会话的全部原始文本内容（包括时序信息）可以自动记录到指定目录中。
     * 该记录，也称为“打字稿”，将被写入由指定的目录中的两个文件typescript-path： NAME，其中包含原始文本数据，和NAME.timing，其中包含时序信息，其中NAME为typescript-name参数提供了值。
     * <p>
     * 此格式与标准UNIX 脚本命令使用的格式兼容 ，并且可以使用scriptreplay（如果已安装）进行重播 。
     * 例如，要重放名为“ NAME” 的打字稿，可以运行：
     * $ scriptreplay NAME.timing NAME
     * <p>
     *
     * @param typescriptPath       应该在其中创建打字稿文件的目录。如果需要记录打字稿，则需要此参数。指定此参数将启用打字记录。如果省略此参数，则不会记录任何打字稿。
     *                             <p>
     * @param createTypescriptPath 如果设置为“ true”，则该typescript-path参数指定的目录（ 如果尚不存在）将自动创建。仅将创建路径中的最终目录-如果路径中较早的其他目录不存在，则自动创建将失败，并且将记录错误。
     *                             此参数是可选的。默认情况下，typescript-path不会自动创建由参数指定的目录 ，并且将尝试在不存在的目录中记录打字稿的尝试记录为错误。
     *                             仅当启用打字记录时，此参数才有效。如果typescript-path未指定，则将禁用打字稿记录，并且将忽略此参数。
     *                             <p>
     * @param typescriptName       确定打字稿的数据和计时文件的名称时要使用的基本文件名。此参数是可选的。如果省略，将使用值“ typescript”代替。
     *                             每个打字稿由两个文件组成，这些文件是在所指定的目录中创建的 typescript-path： NAME，其中包含原始文本数据；而 NAME.timing，其中包含计时信息，其中 NAME是为typescript-name 参数提供的值。
     *                             仅当启用打字记录时，此参数才有效。如果typescript-path未指定，则将禁用打字稿记录，并且将忽略此参数。
     */
    public void textSessionRecording(String typescriptPath, boolean createTypescriptPath, String typescriptName) {
        super.getGuacamoleConfiguration().setParameter("typescript-path", typescriptPath);
        super.getGuacamoleConfiguration().setParameter("create-typescript-path", String.valueOf(createTypescriptPath));
        if (typescriptName != null) {
            super.getGuacamoleConfiguration().setParameter("typescript-name", typescriptName);
        }
    }

    /**
     * SFTP
     * <p>
     * Guacamole支持使用SFTP（大多数SSH服务器中内置的文件传输协议）通过SSH进行文件传输。
     * 如果在Guacamole SSH连接上启用了SFTP，则用户将能够按照第15章“ 使用Guacamole”中的说明上载和下载文件 。
     *
     * @param enableSftp        是否应启用文件传输。如果设置为“ true”，则将允许用户使用SFTP从SSH服务器上载或下载文件。
     *                          Guacamole包含guacctl实用程序，该 实用程序可控制用户通过SSH连接在SSH服务器上运行时文件的下载和上传。
     *                          <p>
     * @param sftpRootDirectory 通过Guacamole的文件浏览器向连接的用户公开的目录 。如果省略，则默认使用根目录。
     */
    public void sftp(boolean enableSftp, String sftpRootDirectory) {
        super.getGuacamoleConfiguration().setParameter("enable-sftp", String.valueOf(enableSftp));
        if (sftpRootDirectory != null) {
            super.getGuacamoleConfiguration().setParameter("sftp-root-directory", sftpRootDirectory);
        }
    }

}
